﻿@page "/Dialog"

@using FluentUI.Demo.Shared.Pages.Dialog.Examples;

<h1>Dialog</h1>

<p>As defined by the <a href="https://www.w3.org/WAI/ARIA/apg/patterns/dialog_modal/" target="_blank" rel="noopener noreferrer">W3C</a>:</p>
<blockquote>
    <p>
        A dialog is a window overlaid on either the primary window or another dialog window. Windows under a modal dialog are inert.
        That is, users cannot interact with content outside an active dialog window. Inert content outside an active dialog is typically visually
        obscured or dimmed so it is difficult to discern, and in some implementations, attempts to interact with the inert content cause the dialog
        to close.
    </p>
    <p>
        Like non-modal dialogs, modal dialogs contain their tab sequence. That is, Tab and Shift + Tab do not move focus outside
        the dialog. However, unlike most non-modal dialogs, modal dialogs do not provide means for moving keyboard focus outside the dialog window
        without closing the dialog.
    </p>
</blockquote>

<p>
    <code>&lt;FluentDialog&gt;</code> wraps the <code>&lt;fluent-dialog&gt;</code> element, a web component implementation of a dialog leveraging
    the Fluent UI design system. <code>&lt;FluentDialog&gt;</code> acts as a shell for the dialog content, which can be specified in a number of ways.
</p>
<h2>DialogService</h2>
<p>
    The <code>DialogService</code> is a service which is used to show different types of dialogs. It is registered as a scoped service, so it can be injected into
    pages/components that use it. For more information on the <code>DialogService</code>, see the <a href="DialogService">Dialog Service</a> page.
</p>

<h2>Dialog content</h2>
<p>
    Normally, the dialog content is specified by a component which implements <code>IDialogContentComponent&lt;T&gt;</code>. This component is then
    passed to the <code>DialogService</code> to be shown. The <code>DialogService</code> will then render a <code>&lt;FluentDialog&gt;</code> with
    the component inside of it.
</p>
<p>
    Alternatively, the dialog content can be specified manually by setting the <code>ChildContent</code> parameter of <code>&lt;FluentDialog&gt;</code>.
    This is useful if you want to show a simple dialog without having to create a component for it or if you do not want to use the <code>DialogService</code> for it.
    <br />
    When using the <code>DialogService</code>, for displaying a regular dialog, the dialog will always be shown centered on the screen.
</p>
<blockquote>
    During the WASM DotNet Publication process, the unused classes are automatically removed from the final library.
    The Dialog razor file will be removed if no reference are set by your code.
    For example, if you call <code>var = await DialogService.ShowDialogAsync&lt;SimpleDialog>(simplePerson, parameters);</code> the <b>SimpleDialog</b> will be removed by the WASM Publication process.
    You can configure this behavior by setting the <a href="https://learn.microsoft.com/aspnet/core/blazor/host-and-deploy/configure-trimmer">PublishTrimmed</a> property in your project file
    or you can create a temporary instance <code>var temp1 = new SimpleDialog();</code> to force the Publication process to keep this class in the final library.
</blockquote>

<h2>Exchange data between dialog and calling component</h2>
<p>
    There are two ways available to exchange data between the dialog and the component which shows it. The first is by capturing the returned
    <code>IDialogReference</code> from one of the <code>DialogService.Show...Async</code> methods and then use that reference to get the dialog's
    result (of type <code>DialogResult</code>). The second is by using an <code>EventCalback</code> parameter as part of the
    <code>DialogParameters</code>. Both ways are demonstated in the samples below.
</p>
<h2>Dialog provider</h2>
<strong>IMPORTANT!!</strong>
<p>
    Dialogs are rendered by the <code>&lt;FluentDialogProvider /&gt;</code> component. This component needs to be added to the main layout of your application/site.
    You typically do this in the <code>MainLayout.razor</code> file at the end of the <code>&lt;main&gt;</code> section like this:
</p>
<p>
    <strong>
        For the Dialogs to work properly, the <code>&lt;FluentDialogProvider/&gt;</code> needs interactivity! <p>
            <strong>
                For the Dialogs to work properly, the <code>&lt;FluentDialogProvider/&gt;</code> needs interactivity! If you are using "per page" interactivity, make sure to add a <code>@@rendermode</code> to
                either the provider itself of the component the provider is placed in.
            </strong>
        </p>Be sure to add a <code>@@rendermode</code> to
        either the provider itself of the component the provider is placed in.
    </strong>
</p>
<CodeSnippet>
    &lt;main&gt;
    &lt;nav&gt;
    :
    &lt;/nav&gt;
    &lt;div class=&quot;content&quot;&gt;
    &lt;article id=&quot;article&quot;&gt;
    @@Body
    &lt;/article&gt;
    &lt;/div&gt;
    &lt;FluentDialogProvider /&gt;
    &lt;/main&gt;
</CodeSnippet>

<h2 id="example">Examples</h2>
<p>
    These examples show how to use the <code>DialogService</code> to display a dialog. The content of the dialog is specified by
    a component which implements <code>IDialogContentComponent&lt;T&gt;</code>. Here, that is done in <code>SimpleDialog.razor</code>. The dialog is automatically styled and centered.
</p>
<p>
    Interaction with parent dialog can be made by injecting FluentDialog as Cascading Parameter. See <code>SimpleDialog.razor</code> for more details.
</p>

<DemoSection Title="DialogService with IDialogReference" MaxHeight="500px" Component="@typeof(DialogServiceExample)" AdditionalFiles="@(new[] {"SimpleDialog.razor"})">
    <Description>
        This example shows how to use async methods to display a dialog and get the result back from it.
    </Description>
</DemoSection>

<DemoSection Title="Customized Dialog" Component="@typeof(DialogCustomizableExample)" AdditionalFiles="@(new[] {"SimpleCustomizedDialog.razor"})">
    <Description>
        <p>
            This example shows how to open a Dialog using the <code>DialogService</code>. The dialog is customized by specifying a header,
            footer and body by leveraging the <code>FluentDialogHeader</code>, <code>FluentDialogFooter</code> and <code>FluentDialogBody</code> parameters.
        </p>
        <p>
            The dialog can <b>not</b> be dismissed by clicking on the overlay. This is achieved by setting the dialog parameter <code>PreventDismissOnOverlayClick</code> to <code>true</code>.
        </p>
    </Description>
</DemoSection>

<DemoSection Title="Editable Dialog" Component="@typeof(DialogEditableExample)" AdditionalFiles="@(new[] { "SimpleEditDialog.razor" })">
    <Description>
        <p>
            This example shows how to open a Dialog containing editable fields.
        </p>
    </Description>
</DemoSection>

<DemoSection Title="DialogService with EventCallback" MaxHeight="500px" Component="@typeof(DialogServiceCallbackExample)" AdditionalFiles="@(new[] {"SimpleDialog.razor"})">
    <Description>
        This example shows how to use an <code>EventCallback</code> parameter to get data back from the dialog.
    </Description>
</DemoSection>

<DemoSection Title="DialogService with Custom Animations" MaxHeight="500px" Component="@typeof(DialogServiceAnimationCallbackExample)" AdditionalFiles="@(new[] {"SimpleDialog.razor"})">
    <Description>
        This example shows how to use <code>EventCallback</code> parameters to animate dialogs when they appear and disappear.
    </Description>
</DemoSection>


<DemoSection Title="Dialog without using DialogService" MaxHeight="500px" Component="@typeof(DialogDefault)" CollocatedFiles="@(new[] {"css"})">
    <Description>
        This example shows a simple dialog created by specifying its content manually (see the Razor tab). Because of this, the dialog is not automatically styled.
        A CSS file has been added to set the width, height and padding of the dialog.
    </Description>
</DemoSection>

<DemoSection Title="SimpleDialog as component" MaxHeight="500px" Component="@typeof(DialogSimpleDialog)">
    <Description>
        For a component to be useable in a dialog, it just needs to inherit from <code>IDialogContentComponent&lt;T&gt;</code>.
        They can still be used as a normal component as well. This example shows the <code>SimpleDialog</code> component from the
        previous example being rendered directly in the page.
    </Description>
</DemoSection>

<h2 id="documentation">Documentation</h2>

<ApiDocumentation Component="typeof(FluentDialogProvider)" />

<ApiDocumentation Component="typeof(FluentDialog)" />

<p>To alter the properties of a dialog which uses the <code>DialogService</code> to display it, use the <code>DialogParameters</code> class.</p>
<blockquote>
    Note: Not all properties can be used for all types of dialogs. For example, the <code>DialogParameters</code> class has a <code>Height</code> property,
    which is ignored when displaying a Panel.
</blockquote>

<ApiDocumentation Component="typeof(DialogParameters<>)" GenericLabel="TData" />

<h3>Dialog header and footer</h3>
<p>The dialog header and footer can be changed by using the <code>FluentDialogHeader</code> and <code>FluentDialogFooter</code> component.</p>
<p>
    The default implementation uses the <code>FluentDialogHeader</code> and <code>FluentDialogFooter</code> components (see documentation below).
    You can use the content of these components as the base for your own implementation:
</p>

<h4>Default dialog header (simplified version)</h4>

<CodeSnippet>
    &lt;FluentStack Orientation="Orientation.Horizontal" VerticalAlignment="VerticalAlignment.Top">
    &lt;div style="width: 100%;">
    &lt;FluentLabel Typo="Typography.PaneHeader">&commat;Title&lt;/FluentLabel>
    &lt;/div>
    &lt;FluentButton Appearance="Appearance.Stealth">
    &lt;FluentIcon Icon="CoreIcons.Regular.Size24.Dismiss" />
    &lt;FluentButton>
    &lt;/FluentStack>
</CodeSnippet>

<h4>Default dialog footer (simplified version)</h4>

<CodeSnippet>
    &lt;FluentStack Orientation="Orientation.Horizontal" HorizontalAlignment="HorizontalAlignment.Right" VerticalAlignment="VerticalAlignment.Bottom">
    &lt;FluentButton Title="&commat;PrimaryAction" Appearance="Appearance.Accent" Disabled="&commat;PrimaryActionEnabled">
    &commat;PrimaryAction
    &lt;/FluentButton>
    &lt;FluentButton Title="&commat;SecondaryAction" Appearance="Appearance.Neutral" Disabled="&commat;SecondaryActionEnabled">
    &commat;SecondaryAction
    &lt;/FluentButton>
    &lt;/FluentStack>
</CodeSnippet>

<ApiDocumentation Component="typeof(FluentDialogHeader)" />

<ApiDocumentation Component="typeof(FluentDialogFooter)" />

<ApiDocumentation Component="typeof(FluentDialogBody)" />
